# 首先我们定义一个不带装饰器的普通函数


def now():
    print("2019-4-20")


f = now
f()  # 输出2019-4-20
print(f.__name__)  # 输出now

# 现在，假设我们要增强now()函数的功能，在函数调用前后自动打印日志，但又不希望修改now()函数的定义，
# 这种在代码运行期间动态增加功能的方式，称之为“装饰器”（Decorator）。
# 本质上，decorator就是一个返回函数的高阶函数。所以，我们要定义一个能打印日志的“装饰器”decorator
# 装饰器实际上就是一个函数，有两个特别之处
# 1.参数是一个函数（如下例中的func） 2.返回值是一个函数


def log(func):
    def wrapper(*args, **kw):
        print('call %s' % func.__name__)
        return func(*args, **kw)
    return wrapper


@log  # 在执行now()时，相当于执行 now = log(now)
def now():
    print('2019-4-20')


now()  # 输出 call now 2019-4-20


# 如果decorator本身需要传入参数，那就需要编写一个返回decorator的高阶函数，写出来会更复杂。
# 比如，要自定义log的文本：
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('call %s' % func.__name__)
            return func(*args, **kw)
        return wrapper
    return decorator


@log('执行')  # 相当于now = log('执行')(now)
def now():
    print('2019-4-20')


now()  # 输出 call now 2019-4-20
